window._getUserMedia = function (constraints, cb) {
    var error;
    var _getUserMedia = null;
    var haveOpts = arguments.length === 2;
    var defaultOpts = {video: true, audio: false};

    var denied = 'PermissionDeniedError';
    var altDenied = 'PERMISSION_DENIED';
    var notSatisfied = 'ConstraintNotSatisfiedError';

    if (!haveOpts) {
        cb = constraints;
        constraints = defaultOpts;
    }

    _getUserMedia = (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) ?
                     navigator.mediaDevices :
                    (
                      (navigator.mozGetUserMedia || navigator.webkitGetUserMedia) ? {
                        getUserMedia: function(c) {
                          return new Promise(function(y, n) {
                            (navigator.mozGetUserMedia ||
                            navigator.webkitGetUserMedia).call(navigator, c, y, n);
                          });
                        }
                      } : null
                    );

    if (typeof navigator === 'undefined' || !_getUserMedia) {

        error = new Error('MediaStreamError');
        error.name = 'NotSupportedError';

        return setTimeout(function () {
            cb(error);
        }, 0);
    }

    // Older versions of firefox (< 21) apparently claim support but user media does not actually work
    if (navigator.userAgent.match(/Firefox\D+(\d+)/)) {
      if (parseInt(RegExp.$1, 10) < 21) _getUserMedia = null;
    }

    if (!constraints.audio && !constraints.video) {
        error = new Error('MediaStreamError');
        error.name = 'NoMediaRequestedError';

        return setTimeout(function () {
            cb(error);
        }, 0);
    }

    _getUserMedia.getUserMedia(constraints)
    .then(function (stream) {
        cb(null, stream);
    }).catch(function (err) {
        var error;

        if (typeof err === 'string') {
            error = new Error('MediaStreamError');
            if (err === denied || err === altDenied) {
                error.name = denied;
            } else {
                error.name = notSatisfied;
            }
        } else {

            error = err;
            if (!error.name) {
                if (error[denied]) {
                    err.name = denied;
                } else {
                    err.name = notSatisfied;
                }
            }
        }

        cb(error);
    });
};